#ifndef POINTUTILITIESTESTS_H
#define POINTUTILITIESTESTS_H

#include<QtTest/QtTest>
#include<QPointF>
#include<vector>
#include<algorithm>

#include "Curves/PointUtilities.h"

using namespace Utilities;
using namespace std;

class PointUtilitiesTest : public QObject
{
    Q_OBJECT
private slots:
    void ComparisonFullTest()
    {
        // with
        vector<QPointF> points;
        vector<QPointF> expected;
        // where
        points.push_back(QPointF::QPointF(2.0,1.0));
        points.push_back(QPointF::QPointF(1.0,1.0));
        points.push_back(QPointF::QPointF(1.0,2.0));
        points.push_back(QPointF::QPointF(0.0,0.0));

        expected.push_back(QPointF::QPointF(0.0,0.0));
        expected.push_back(QPointF::QPointF(1.0,1.0));
        expected.push_back(QPointF::QPointF(1.0,2.0));
        expected.push_back(QPointF::QPointF(2.0,1.0));
        // do
        std::stable_sort(points.begin(), points.end(), IPointCompare<QPointF>);

        QCOMPARE(points, expected);
    }

    void CrossProductStraightLineReturnsZero()
    {
        // with
        QPointF p1(1.0,1.0),
                p2(2.0,2.0),
                p3(3.0,3.0);

        double value = IPointCrossProduct<QPointF>(p1,p2,p3);
        // do
        QVERIFY(value == 0);
    }

    void CrossProductRightTurnReturnsNegative()
    {
        // with
        QPointF p1(1.0,1.0),
                p2(2.0,2.0),
                p3(3.0,1.0);

        double value = IPointCrossProduct<QPointF>(p1,p2,p3);
        // do
        QVERIFY(value < 0);
    }

    void CrossProductLeftTurnReturnsPositive()
    {
        QPointF p1(1.0,1.0),
                p2(2.0,2.0),
                p3(1.0,2.0);

        double value = IPointCrossProduct<QPointF>(p1,p2,p3);
        // do
        QVERIFY(value > 0);
    }

    void ConvexHullSinglePointTest()
    {
        vector<QPointF> test1;
        test1.push_back(QPointF(100, 100));
        vector<QPointF> answ1(test1);

        QCOMPARE( IPointConvexHull<QPointF>(test1), answ1 );
    }

    void ConvexHullTriangleWithPointInsideTest()
    {
        vector<QPointF> test2;
        test2.push_back(QPointF(1,1));
        test2.push_back(QPointF(1,4));
        test2.push_back(QPointF(4,1));
        vector<QPointF> answ2(test2);
        test2.push_back(QPointF(2,2));

        QCOMPARE( IPointConvexHull<QPointF>(test2), answ2 );
    }

//    void ConvexHullDoubledPointsTest()
//    {
//        vector<QPointF> test;
//        test.push_back(QPointF(1,1));
//        test.push_back(QPointF(1,1));
//        test.push_back(QPointF(2,2));
//        test.push_back(QPointF(2,1));
//        test.push_back(QPointF(3,2));
//        test.push_back(QPointF(4,2));
//        vector<QPointF> answer;
//        answer.push_back(QPointF(1,1));
//        answer.push_back(QPointF(2,2));
//        answer.push_back(QPointF(4,2));
//        answer.push_back(QPointF(2,1));

//        QCOMPARE( IPointConvexHull<QPointF>(test), answer );
//    }
    void RotationSinglePointWithOrigin90DegreeTest()
    {
        // with
        QPointF origin(0,0);
        QPointF point(5,0);
        double angle = -90;
        QPointF answer(0,5);
        // do
        IPointRotate<QPointF>( point, origin, angle );
        QCOMPARE( point, answer );
    }

    void RotationMultiplePointsWithOrigin90DegreeTest()
    {
        // with
        QPointF origin(0,0);
        double angle = 90;
        vector<QPointF> points;
        points.push_back( QPointF(0,5) );
        points.push_back( QPointF(0,7) );
        points.push_back( QPointF(0,6) );
        vector<QPointF> answer;
        answer.push_back( QPointF(5,0) );
        answer.push_back( QPointF(7,0) );
        answer.push_back( QPointF(6,0) );
        IPointRotateMultiple<QPointF>( points, origin, angle );
        QCOMPARE( points, answer );
    }

    void CenterOfMassSimpleBoxTest()
    {
        // with
        vector<QPointF> points;
        points.push_back( QPointF(0,0) );
        points.push_back( QPointF(0,2) );
        points.push_back( QPointF(2,0) );
        points.push_back( QPointF(2,2) );
        QPointF answer(1,1);

        QCOMPARE( IPointCenterOfMass<QPointF>( points ), answer );
    }
};


#endif // POINTUTILITIESTESTS_H
